package cn.netdisk.tinynetdisk.controller;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.json.JSONUtil;
import cn.netdisk.tinynetdisk.common.entity.BaseFileContent;
import cn.netdisk.tinynetdisk.common.entity.ResponseData;
import cn.netdisk.tinynetdisk.entity.ChunkFile;
import cn.netdisk.tinynetdisk.entity.FileInfo;
import cn.netdisk.tinynetdisk.service.INetDiskService;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.List;

@RestController
@RequestMapping("/netDisk")
public class NetDiskController {

    @Value("${netDisk.config.baseDir}")
    private String baseDir;
    /**
     * 线程安全的
     */
    @Resource
    private HttpServletRequest request;
    /**
     * 线程安全的
     */
    @Resource
    private HttpServletResponse response;
    @Resource
    private INetDiskService netDiskService;

    /**
     * 获取头部key
     *
     * @return java.lang.String
     * @date 2022/10/10 8:59
     * @author glq
     */
    public String getAuthKey() {
        String key = request.getHeader("authKey");
        //若header不存在key，试图拿快速key
        if (StrUtil.isBlank(key)) {
            key = request.getParameter("authKey");
        }
        if (StrUtil.isNotBlank(key)) {
            return "/" + key;
        } else {
            return "";
        }

    }

    /**
     * 获取文件列表
     *
     * @param suffix 文件后缀
     * @return cn.netdisk.tinynetdisk.common.entity.ResponseData<java.util.List < cn.netdisk.tinynetdisk.entity.FileInfo>>
     * @date 2022/9/30 11:04
     * @author glq
     */
    @GetMapping("getFiles")
    public ResponseData<List<FileInfo>> getFiles(String suffix) {
        if (StrUtil.isNotBlank(suffix)) {
            return ResponseData.createBySuccess(netDiskService.getFileInfo(baseDir + getAuthKey() + suffix));
        }
        return ResponseData.createBySuccess(netDiskService.getFileInfo(baseDir + getAuthKey()));
    }

    /**
     * 创建文件夹
     *
     * @param suffix 文件后缀
     * @return cn.netdisk.tinynetdisk.common.entity.ResponseData<java.lang.Boolean>
     * @date 2022/10/9 11:07
     * @author glq
     */
    @GetMapping("createDir")
    public ResponseData<Boolean> createDir(String suffix) {
        if (StrUtil.isNotBlank(suffix)) {
            return ResponseData.createBySuccess(netDiskService.createDir(baseDir + getAuthKey() + suffix));
        }
        return ResponseData.createBySuccess(false);
    }

    /**
     * 创建文件
     *
     * @param suffix 文件后缀
     * @return cn.netdisk.tinynetdisk.common.entity.ResponseData<java.lang.Boolean>
     * @date 2022/10/9 11:37
     * @author glq
     */
    @GetMapping("createFile")
    public ResponseData<Boolean> createFile(String suffix) throws IOException {
        if (StrUtil.isNotBlank(suffix)) {
            return ResponseData.createBySuccess(netDiskService.createFile(baseDir + getAuthKey() + suffix));
        }
        return ResponseData.createBySuccess(false);
    }


    /**
     * 读取txt文本
     *
     * @param suffix 文件后缀
     * @return cn.netdisk.tinynetdisk.common.entity.ResponseData<cn.netdisk.tinynetdisk.common.entity.BaseFileContent>
     * @date 2022/10/9 18:20
     * @author glq
     */
    @GetMapping("readFile")
    public ResponseData<BaseFileContent> readFile(String suffix) {
        if (StrUtil.isNotBlank(suffix)) {
            return ResponseData.createBySuccess(netDiskService.readFile(baseDir + getAuthKey() + suffix));
        }
        return ResponseData.createBySuccess(null);

    }

    /**
     * 写入txt文本
     *
     * @param body 写入实体参数
     * @return cn.netdisk.tinynetdisk.common.entity.ResponseData<java.lang.Boolean>
     * @date 2022/10/9 18:33
     * @author glq
     */
    @PostMapping("writeFile")
    public ResponseData<Boolean> writeFile(@RequestBody BaseFileContent body) {
        if (StrUtil.isNotBlank(body.getSuffix())) {
            body.setSuffix(baseDir + getAuthKey() + body.getSuffix());
            return ResponseData.createBySuccess(netDiskService.writeFile(body));
        }
        return ResponseData.createBySuccess(null);
    }

    /**
     * 删除文件
     *
     * @param suffix 文件后缀
     * @return cn.netdisk.tinynetdisk.common.entity.ResponseData<java.lang.Boolean>
     * @date 2022/10/13 11:26
     * @author glq
     */
    @GetMapping("deleteFile")
    public ResponseData<Boolean> deleteFile(String suffix) {
        if (StrUtil.isNotBlank(suffix)) {

            return ResponseData.createBySuccess(netDiskService.deleteFile(baseDir + getAuthKey() + suffix));
        }
        return ResponseData.createBySuccess(false);

    }

    /**
     * 文件/文件夹重命名
     *
     * @param suffix  文件后缀
     * @param oldName 旧名称
     * @param newName 新名称
     * @return cn.netdisk.tinynetdisk.common.entity.ResponseData<java.lang.Boolean>
     * @date 2022/10/14 18:05
     * @author glq
     */
    @GetMapping("renameFile")
    public ResponseData<Boolean> renameFile(String suffix, String oldName, String newName) {
        if (StrUtil.isBlank(oldName)) {
            return ResponseData.createByErrorMessage("旧名称不能为空！");
        }
        if (StrUtil.isBlank(newName)) {
            return ResponseData.createByErrorMessage("新名称不能为空！");
        }
        return ResponseData.createBySuccess(netDiskService.renameFile(baseDir + getAuthKey() + suffix, oldName, newName));
    }

    /**
     * 分片上传文件,适用于文件和文件夹
     *
     * @param file 文件
     * @return cn.netdisk.tinynetdisk.common.entity.ResponseData<java.lang.Boolean>
     * @date 2022/10/13 15:26
     * @author glq
     */
    @PostMapping("uploadFile")
    public ResponseData<Boolean> uploadFile(@RequestParam("file") MultipartFile file, ChunkFile chunkFile) throws IOException {

//        System.out.println(chunkFile);
//        System.out.println(file.getOriginalFilename());
//        System.out.println(file.getSize());
        chunkFile.setSuffix(baseDir + getAuthKey() + chunkFile.getSuffix());
        return ResponseData.createBySuccess(netDiskService.uploadFile(chunkFile, file));
    }

    /**
     * 下载文件
     *
     * @param suffix  后缀
     * @param authKey 授权key
     * @return void
     * @date 2022/10/14 16:16
     * @author glq
     */
    @RequestMapping("downloadFile")
    public void downloadFile(String suffix, String authKey) throws IOException {
        if (StrUtil.isBlank(authKey)) {
            response.setHeader("Content-Type", "application/json;charset=utf-8");
            response.getWriter().write(JSONUtil.toJsonStr(ResponseData.createByErrorMessage("密钥不能为空！")));
            response.getWriter().flush();
            response.getWriter().close();
            return;
        }
        if (StrUtil.isBlank(suffix)) {
            response.setHeader("Content-Type", "application/json;charset=utf-8");
            response.getWriter().write(JSONUtil.toJsonStr(ResponseData.createByErrorMessage("文件名称不能为空！")));
            response.getWriter().flush();
            response.getWriter().close();
            return;
        }
        String base = baseDir + getAuthKey() + suffix;
        File file = new File(base);
        ServletOutputStream outputStream = response.getOutputStream();
        FileInputStream fileInputStream = new FileInputStream(file);
        try {
            if (!file.exists()) {
                response.setHeader("Content-Type", "application/json");
                response.getWriter().write(JSONUtil.toJsonStr(ResponseData.createByErrorMessage("文件不存在！")));
                response.getWriter().flush();
                response.getWriter().close();
            } else {


                String[] arr = file.getName().split("\\.");

                response.setHeader("Content-Length", file.length() + "");

                if (arr.length > 1) {
                    response.setHeader("Content-Disposition", "attachment;filename=" + System.currentTimeMillis() + "." + arr[arr.length - 1]);
                } else {
                    response.setHeader("Content-Disposition", "attachment;filename=" + System.currentTimeMillis());
                }


                int len;
                byte[] b = new byte[1024 * 1024 * 30];
                while (true) {

                    len = fileInputStream.read(b);
                    if (len == -1) break;
                    outputStream.write(b, 0, b.length);
                }


            }
        } catch (Exception e) {
            //System.out.println("异常:" + e.getMessage());
        } finally {
            //保证关闭输入流
            fileInputStream.close();
            outputStream.flush();
            outputStream.close();
        }

    }


}
